package study.lanqiao.com;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringEscapeUtils;

import java.util.*;

public class t2021 {
    public static void main(String[] args) {
        t8();
//        Map<String, Object> claims = new HashMap<String, Object>();
//        claims.put("sub", "root");
//        claims.put("created", new Date());
//        String s = Jwts.builder()
//                .setClaims(claims)
//                .setExpiration(new Date(System.currentTimeMillis())) //设置过期时间
//                .signWith(SignatureAlgorithm.HS512, "secret") //设置加密方式和密钥
//                .compact(); //compact函数作用
//        System.out.println(s);
        //t1();
        //t2();
        //t3();
        //t4();
        //t5();
        //t6();
        //t7();
//        String str = StringEscapeUtils.unescapeHtml4("<p>【产品名称】艾酷维多种维生素锌软糖</p>");
//        System.out.println(str);
//        String str2 = StringEscapeUtils.escapeHtml4("<p>【产品名称】艾酷维多种维生素锌软糖</p>");
//        System.out.println(str2);
//        System.out.println(StringEscapeUtils.unescapeHtml4(str2));
    }

    /**
     * 卡片
     */
    public static void t1(){
        int[] keep = new int[10];//kep[i]：即卡片i还剩余多少张
        for (int i = 0; i < 10; i++) {
            keep[i] = 2021;
        }
        int res = 0;//不能被拼出的数字
        for (int i = 1; i <= 20210; i++) {
            int cnt = i;
            while (cnt > 0){
                int tmp = cnt % 10;
                keep[tmp]--;
                if (keep[tmp] < 0){
                    System.out.println(i - 1);//得到结果，i拼不到，因此答案是i-1
                    return;
                }
                cnt /= 10;
            }
        }
    }

    /**
     * 相乘
     */
    public static void t2(){
        long mod = 1000000007;
        long res = -1;
        for (long i = 100000; i <= mod; i++) {
            if (i * 2021 % mod == 999999999){
                res = i;
                break;
            }
        }
        System.out.println(res);
    }

    /**
     * 路径
     */
    public static void t3(){
        int[] dp = new int[2022];
        dp[1] = 0;
        for (int i = 2; i < 2022; i++) {
            int leftRange = Math.max(1,i-21);
            dp[i] = Integer.MAX_VALUE;
            for (int j = leftRange; j <= i - 1; j++) {
                dp[i] = Math.min(dp[j] + f(i,j) , dp[i]);
            }
        }
        System.out.println(dp[2021]);
    }
    //计算x，y最大公约数，其中x>y
    public static int func(int x,int y){
        return y == 0 ? x : func(y,x%y);
    }
    //计算x，y最大公倍数，其中x>y
    public static int f(int x,int y){
        return x * y / func(x,y);
    }

    /**
     *时间显示
     */
    public static void t4(){
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        long cur = 0;
        long mod = 1000 * 60 * 60 * 24;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < t; i++) {
            cur = in.nextLong();
            cur %= mod;
            long h = cur / (1000 * 60 * 60);
            cur %= (1000 * 60 * 60);
            long m = cur / (1000 * 60);
            cur %= 1000 * 60;
            long s = cur / 1000;
            if (h < 10) sb.append("0");
            sb.append(h+":");
            if (m < 10) sb.append("0");
            sb.append(m+":");
            if (s < 10) sb.append("0");
            sb.append(s+"\n");
        }
        System.out.print(sb.toString());
    }

    /**
     * 回路计数 - 注意把数据类型改为long型，以防数据过大导致int被截断
     * 图的遍历复杂度是21的阶乘，赛时不可能跑完，考虑DP
     * 首先
     * 21个点，用21位的二进制01串状压表示每一栋楼是否访问
     * 所以现在的问题就转化成了
     * 如何将一个含有1位1，20位0的二进制数变的21位都是1
     * DP的基本思路：
     * 从初始状态开始，不断的去尝试下一个能到达的楼，并且将楼加入状态中（对应的楼的二进制位变为1），那么如果21位的二进制所有数都变为了1，就说明这是一种可行的路径，将这个路径计数到dp[ (1<<21) - 1][路径的末楼下标]
     * 之后状态转移方程
     * dp[ i ][ j ]表示从状态 i 到 j 的路径数
     * dp[ i + (1 << k) ][ k ] += dp[ i ][ j ];
     * 原状态 i 在楼 j 已经访问过的情况下去尝试将楼 k 加入已访问的点，如果可以，则新的状态会以k为终点，
     * 其路径数为原来的值加上dp[ i ][ j ]
     * 某个楼x是否已经访问过的判断：
     * i >> x & 1 (状态 i 按位右移x位，之后取余) (判断状态 i 二进制数的第 x 位是否为1)
     */
    public static void t5(){
        boolean[][] vis = new boolean[21][21];// vis[i][j]：为false表示i与j不互质，或者i==j
        for (int i = 1; i <= 21; i++) {
            for (int j = i + 1; j <= 21; j++) {
                if (isValid(i,j)){
                    vis[i - 1][j - 1] = true;
                    vis[j - 1][i - 1] = true;
                }
            }
        }
        long[][] dp = new long[1<<21][21];
        dp[1][0] = 1;
        for (int i = 1; i < (1<<21); i++) {
            for (int j = 0; j < 21; j++) {
                if (((i>>j)&1)==0) continue;
                for (int k = 0; k < 21; k++) {
                    if (((i>>k)&1)==1 || !vis[j][k]) continue;
                    dp[i + (1<<k)][k] += dp[i][j];
                }
            }
        }
        long res = 0;
        for (int i = 1; i < 21; i++) {
            res += dp[(1<<21) -1][i];
        }
        System.out.println(res);
        /*boolean[] vis = new boolean[22];
        vis[1] = true;
        int[] path = new int[22];
        path[0] = 1;
        HashSet<String> allPath = new HashSet<String>();
        dfs(1, vis, path, 1, allPath);
        System.out.println(allPath.size());
        for (String s : allPath){
            System.out.println(s);
        }*/
    }

    /**
     * 判断x，y是否互质
     * @param x
     * @param y
     * @return
     */
    public static boolean isValid(int x,int y){
        return gcd(x,y) == 1;
    }

    /**
     * 求x，y最大公约数
     * @param x
     * @param y
     * @return
     */
    public static int gcd(int x,int y){
        return y == 0 ? x : gcd(y,x % y);
    }
    /**
     * 耗时太大，超时，舍去，采用状态dp，见t5()
     * @param i：访问到第i教学楼
     * @param vis：vis[i]为true表示教学楼i被访问过了
     * @param path：访问路径
     * @param size：当前path大小
     * @param allPath：所有可行路径
     */
    public static void dfs(int i, boolean[] vis, int[] path, int size, HashSet<String> allPath){
        if (size == 21){
            //if (!isValid(path[0],path[size - 1])) return;
            String s = "";
            for (int j = 0; j < size; j++) {
                s += path[j] + "_";
            }
            if (!allPath.contains(s)) allPath.add(s);
            return;
        }
        for (int j = 2; j <= 21; j++) {
            if (i != j && isValid(j,path[size - 1]) && !vis[j]){
                vis[j] = true;
                path[size] = j;
                dfs(j,vis,path,size + 1,allPath);
                vis[j] = false;
            }
        }
    }

    /**
     * 直线   答案：40257
     * (y-y1) = (x-x1)(y2-y1)/(x2-x1) -> (x2-x1)y-(y2-y1)x = x2y1-x1y2
     * 只要(x2-x1)、(y2-y1)、x2y1-x1y2出现不同的形态就是不同的形态
     * 注意一组系数可能不是最简，需要约去最大公约数
     */
    static class LineNode{
        public int x;
        public int y;
        public LineNode(int x,int y){
            this.x = x;
            this.y = y;
        }
    }
    public static void t6(){
        HashSet<String> set = new HashSet<String>();
        List<LineNode> list = new ArrayList<LineNode>();
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 21; j++) {
                list.add(new LineNode(i,j));
            }
        }
        //不包含水平和垂直线
        for (int i = 0; i < list.size(); i++) {
            for (int j = i + 1; j < list.size(); j++) {
                int x1 = list.get(i).x;
                int y1 = list.get(i).y;
                int x2 = list.get(j).x;
                int y2 = list.get(j).y;
                if (x1 == x2 || y1 == y2) continue;
                int a = x2 - x1;
                int b = y2 - y1;
                int c = x2 * y1 - x1 * y2;
                int gcd = gcd(a,gcd(b,c));
                //换位最约形式
                a /= gcd;
                b /= gcd;
                c /= gcd;
                set.add(new String(a+"_"+b+"_"+c));
            }
        }
        System.out.println(set.size() + 20 + 21); //加上水平和垂直线的数量
    }

    /**
     * 最少砝码
     * 找规律
     * 1个砝码最大称到1
     * 2个砝码最大称到4
     * 3个砝码最大称到13
     * 新一级的砝码最大称到：上一级砝码上限+1
     */
    public static void t7(){
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        int n = 0;
        StringBuilder sb = new StringBuilder();
        while (t-- > 0){
            n = in.nextInt();
            if (n == 1){
                sb.append(1+"\n");
                continue;
            }
            long range = 1; //需要设置为long，防止3 * range + 1的时候超出int范围
            for (int i = 2; i <= n; i++) {
                range = 3 * range + 1;
                if (range >= n){
                    sb.append(i+"\n");
                    break;
                }
            }
        }
        System.out.print(sb.toString());
    }

    /**
     * 双向排序
     */
    public static void t8(){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        Integer[] arr = new Integer[n];
        for (int i = 0; i < n; i++) {
            arr[i] = i + 1;
        }
        int op = 0;
        int pos = 0;
        for (int i = 0; i < m; i++) {
            op = in.nextInt();
            pos = in.nextInt();
            if (op == 0){
                Arrays.sort(arr, 0, pos, new Comparator<Integer>() {
                    public int compare(Integer o1, Integer o2) {
                        return o2 - o1;
                    }
                });
            }else{
                Arrays.sort(arr,pos - 1,n);
            }
        }
        StringBuilder sb = new StringBuilder();
        sb.append(arr[0]);
        for (int i = 1; i < n; i++) {
            sb.append(" " + arr[i]);
        }
        System.out.println(sb.toString());
    }
}
